//********************************************************************
//	created:	13:10:2011   9:22
//	filename: 	main-win32.cpp
//	author:		tiamo
//	purpose:	main for windows
//********************************************************************

#include "stdafx.h"

#ifdef WIN32

namespace
{
	//
	// service
	//
	Server																	gServer;

	//
	// stauts
	//
	SERVICE_STATUS															gServiceStatus;

	//
	// status handle
	//
	SERVICE_STATUS_HANDLE													gServiceStatusHandle;

	//
	// report service status
	//
	VOID reportServiceStatus(DWORD currentState, DWORD win32ExitCode, DWORD waitHint)
	{
		static DWORD checkPoint												= 1;

		gServiceStatus.dwCurrentState										= currentState;
		gServiceStatus.dwWin32ExitCode										= win32ExitCode;
		gServiceStatus.dwWaitHint											= waitHint;

		if(currentState == SERVICE_START_PENDING)
			gServiceStatus.dwControlsAccepted								= 0;
		else 
			gServiceStatus.dwControlsAccepted								= SERVICE_ACCEPT_STOP;

		if(currentState == SERVICE_RUNNING || currentState == SERVICE_STOPPED)
			gServiceStatus.dwCheckPoint										= 0;
		else 
			gServiceStatus.dwCheckPoint										= checkPoint++;

		SetServiceStatus(gServiceStatusHandle, &gServiceStatus);
	}

	//
	// service control handler
	//
	VOID WINAPI serviceControlHandler(DWORD ctrlType)
	{
		if(ctrlType == SERVICE_CONTROL_STOP)
		{  
			reportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
			Server::getSingleton()->stop();
			return;
		} 

		reportServiceStatus(gServiceStatus.dwCurrentState, NO_ERROR, 0);
	}

	//
	// service main
	//
	VOID WINAPI serviceMain(DWORD argc, LPTSTR* argv)
	{
		//
		// register control handler
		//
		gServiceStatusHandle												= RegisterServiceCtrlHandler(_T("u2daemon"), &serviceControlHandler);
		if(!gServiceStatusHandle)
			return;

		gServiceStatus.dwServiceType										= SERVICE_WIN32_OWN_PROCESS;
		gServiceStatus.dwServiceSpecificExitCode							= 0;

		//
		// report status to SCM
		//
		reportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 3000);

		//
		// start run
		//
		Server::getSingleton()->start(0, nullptr);
		reportServiceStatus(SERVICE_RUNNING, NO_ERROR, 0);
		Server::getSingleton()->run();

		//
		// report status to SCM
		//
		reportServiceStatus(SERVICE_STOPPED, NO_ERROR, 3000);
	}

	//
	// console handler
	//
	static BOOL WINAPI consoleHandler(DWORD ctrlType)
	{
		switch(ctrlType)
		{
		case CTRL_C_EVENT:
		case CTRL_BREAK_EVENT:
		case CTRL_CLOSE_EVENT:
		case CTRL_LOGOFF_EVENT:
		case CTRL_SHUTDOWN_EVENT:
			Server::getSingleton()->stop();
			return TRUE;
			break;
		}

		return FALSE;
	}
}

//
// main
//
int _tmain(int argc, _TCHAR* argv[])
{
	//
	// change root directory
	//
	SetCurrentDirectoryA("..");

	//
	// start winsock
	//
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//
	// run as service
	//
	SERVICE_TABLE_ENTRY dispatchTable[]										= {{_T("u2daemon"), &serviceMain}, {nullptr, nullptr}};
	if(StartServiceCtrlDispatcher(dispatchTable))
		return 0;

	//
	// run as console program if start service failed
	//
	SetConsoleCtrlHandler(&consoleHandler, TRUE);
	Server::getSingleton()->start(0, nullptr);
	Server::getSingleton()->run();
}
#endif
